#include "stdafx.h"
#include "ParticleEmitter.h"

namespace MyGame {

ParticleEmitter::ParticleEmitter(Game* game) : GameComponent(game) {
    this->beginScale = D3DXVECTOR3(1, 1, 1);
    this->effect = NULL;
    this->endScale = D3DXVECTOR3(1, 1, 1);
    this->generatedParticles = 0;
    this->gravity = D3DXVECTOR3(0, 0, 0);
    this->lastParticlePosition = D3DXVECTOR3(0, 0, 0);
    this->particleLife = 0;
    this->period = 0;
    this->position = D3DXVECTOR3(0, 0, 0);
    this->prevPosition = D3DXVECTOR3(0, 0, 0);
    this->speed = D3DXVECTOR3(0, 0, 0);
    this->timer = 0;
}

ParticleEmitter::~ParticleEmitter(void) {
}

D3DXVECTOR3 ParticleEmitter::GetBeginScale() const {
    return this->beginScale;
}

void ParticleEmitter::SetBeginScale(D3DXVECTOR3 val) {
    this->beginScale = val;
}

Quad* ParticleEmitter::GetEffect() const {
    return this->effect;
}

void ParticleEmitter::SetEffect(Quad* val) {
    this->effect = val;
}

D3DXVECTOR3 ParticleEmitter::GetEndScale() const {
    return this->endScale;
}

void ParticleEmitter::SetEndScale(D3DXVECTOR3 val) {
    this->endScale = val;
}

D3DXVECTOR3 ParticleEmitter::GetGravity() const {
    return this->gravity;
}

void ParticleEmitter::SetGravity(D3DXVECTOR3 val) {
    this->gravity = val;
}

D3DXVECTOR3 ParticleEmitter::GetSpeed() const {
    return this->speed;
}

void ParticleEmitter::SetSpeed(D3DXVECTOR3 val) {
    this->speed = val;
}

FLOAT ParticleEmitter::GetParticleLife() const {
    return this->particleLife;
}

void ParticleEmitter::SetParticleLife(FLOAT val) {
    this->particleLife = val;
}

ParticleSystem* ParticleEmitter::GetParticleSystem() const {
    return this->particleSystem;
}

void ParticleEmitter::SetParticleSystem(ParticleSystem* val) {
    this->particleSystem = val;
}

FLOAT ParticleEmitter::GetPeriod() const {
    return this->period;
}

void ParticleEmitter::SetPeriod(FLOAT val) {
    this->period = val;
}

D3DXVECTOR3 ParticleEmitter::GetPosition() const {
    return this->position;
}

void ParticleEmitter::SetPosition(D3DXVECTOR3 val) {
    this->prevPosition = this->position;
    this->position = val;
}

void ParticleEmitter::Emit() {
    Particle* particle = new Particle();
    particle->BeginScale = this->beginScale;
    particle->Effect = this->effect;
    particle->EndScale = this->endScale;
    particle->Gravity = this->gravity;
    particle->Life = this->particleLife;
    particle->LifeMax = this->particleLife;
    particle->Position = this->position;
    particle->Speed = this->speed;
    this->particleSystem->Add(particle);
    this->generatedParticles++;
    this->lastParticlePosition = this->position;
}

void ParticleEmitter::Update(FLOAT timeDelta) {
    int missed = (int)(timeDelta / this->period);
    if (missed > 0 && this->generatedParticles > 0) {
        for (int i = 1; i <= missed; ++i) {
            FLOAT life = this->particleLife - i * this->period;
            if (life <= 0) {
                continue;
            }

            Particle* particle = new Particle();
            particle->BeginScale = this->beginScale;
            particle->Effect = this->effect;
            particle->EndScale = this->endScale;
            particle->Gravity = this->gravity;
            particle->Life = life;
            particle->LifeMax = this->particleLife;
            D3DXVECTOR3 newPos;
            D3DXVECTOR3 lastPos = this->generatedParticles > 0 ? this->lastParticlePosition : this->prevPosition;
            D3DXVec3Lerp(&newPos, &this->position, &lastPos, (FLOAT)i / missed);
            particle->Position = newPos;
            particle->Speed = this->speed;
            this->particleSystem->Add(particle);
            this->generatedParticles++;
            timeDelta -= this->period;
        }

        this->lastParticlePosition = this->position;
    }

    if (this->timer > 0) {
        this->timer -= timeDelta;
    }

    if (this->timer <= 0) {
        this->timer = this->period - this->timer;
        this->Emit();
    }
}

}
